package com.zan.utils;

import com.zan.model.Field;
import com.zan.model.Table;

import java.sql.*;
import java.util.ArrayList;
import java.util.List;

/**
 * @Author Zan
 * @Create 2024/5/24 14:29
 * @ClassName: DatabaseUtils
 * @Description : 获取表字段工具类
 */
public class DatabaseUtils {

    public static Table getTableMetadata(String tableName, Connection connection) throws SQLException {
        List<Field> fields = new ArrayList<>();
        List<Field> commonFields = new ArrayList<>();

        DatabaseMetaData databaseMetaData = connection.getMetaData();
        ResultSet resultSet = databaseMetaData.getColumns(null, null, tableName, null);
        ResultSet primaryKeyResultSet = databaseMetaData.getPrimaryKeys(null, null, tableName);

        List<String> primaryKeys = new ArrayList<>();
        while (primaryKeyResultSet.next()) {
            primaryKeys.add(primaryKeyResultSet.getString("COLUMN_NAME"));
        }

        StringBuilder fieldNamesBuilder = new StringBuilder();
        while (resultSet.next()) {
            String columnName = resultSet.getString("COLUMN_NAME");
            String propertyName = toCamelCase(columnName);
            String jdbcType = getJdbcType(resultSet.getInt("DATA_TYPE")); // 获取字段的jdbcType
            String comment = resultSet.getString("REMARKS"); // 获取字段的注释
            boolean isPrimaryKey = primaryKeys.contains(columnName);

            Field field = new Field(columnName, propertyName, jdbcType, comment, isPrimaryKey);
            if (isPrimaryKey) {
                fields.add(field);
            } else {
                commonFields.add(field);
            }

            fieldNamesBuilder.append(columnName).append(", ");
        }

        if (fieldNamesBuilder.length() > 0) {
            fieldNamesBuilder.setLength(fieldNamesBuilder.length() - 2);
        }

        return new Table(fields, commonFields, fieldNamesBuilder.toString());
    }

    private static String toCamelCase(String s) {
        String[] parts = s.split("_");
        if (parts.length == 1) {
            return s;
        }
        StringBuilder camelCaseString = new StringBuilder();
        for (int i = 0; i < parts.length; i++) {
            if (i == 0) {
                camelCaseString.append(parts[i]);
            } else {
                camelCaseString.append(toProperCase(parts[i]));
            }
        }
        return camelCaseString.toString();
    }

    private static String toProperCase(String s) {
        return s.substring(0, 1).toUpperCase() + s.substring(1).toLowerCase();
    }

    private static String getJdbcType(int dataType) {
        switch (dataType) {
            case Types.ARRAY:
                return "ARRAY";
            case Types.BIGINT:
                return "BIGINT";
            case Types.BINARY:
                return "BINARY";
            case Types.BIT:
                return "BIT";
            case Types.BLOB:
                return "BLOB";
            case Types.BOOLEAN:
                return "BOOLEAN";
            case Types.CHAR:
                return "CHAR";
            case Types.CLOB:
                return "CLOB";
            case Types.DATALINK:
                return "DATALINK";
            case Types.DATE:
                return "DATE";
            case Types.DECIMAL:
                return "DECIMAL";
            case Types.DISTINCT:
                return "DISTINCT";
            case Types.DOUBLE:
                return "DOUBLE";
            case Types.FLOAT:
                return "FLOAT";
            case Types.INTEGER:
                return "INTEGER";
            case Types.JAVA_OBJECT:
                return "JAVA_OBJECT";
            case Types.LONGNVARCHAR:
                return "LONGNVARCHAR";
            case Types.LONGVARBINARY:
                return "LONGVARBINARY";
            case Types.LONGVARCHAR:
                return "LONGVARCHAR";
            case Types.NCHAR:
                return "NCHAR";
            case Types.NCLOB:
                return "NCLOB";
            case Types.NULL:
                return "NULL";
            case Types.NUMERIC:
                return "NUMERIC";
            case Types.NVARCHAR:
                return "NVARCHAR";
            case Types.OTHER:
                return "OTHER";
            case Types.REAL:
                return "REAL";
            case Types.REF:
                return "REF";
            case Types.REF_CURSOR:
                return "REF_CURSOR";
            case Types.ROWID:
                return "ROWID";
            case Types.SMALLINT:
                return "SMALLINT";
            case Types.SQLXML:
                return "SQLXML";
            case Types.STRUCT:
                return "STRUCT";
            case Types.TIME:
                return "TIME";
            case Types.TIMESTAMP:
                return "TIMESTAMP";
            case Types.TINYINT:
                return "TINYINT";
            case Types.VARBINARY:
                return "VARBINARY";
            case Types.VARCHAR:
                return "VARCHAR";
            default:
                return String.valueOf(dataType);
        }
    }
}
